<!--
 * @Author: 赵克强 huohuo625@163.com
 * @Date: 2024-08-13 14:44:57
 * @LastEditors: 赵克强 huohuo625@163.com
 * @LastEditTime: 2024-09-13 11:59:43
 * @FilePath: \hy-ui\src\views\taskMassage\components\task\index.vue
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
  <div class="schedule" v-loading="loading">
    <div class="schedule_left">
      <FullCalendar
        ref="fullCalendar"
        :options="calendarOptions"
      ></FullCalendar>
    </div>
    <div class="schedule_right">
      <div class="searchTitle">
        <el-row :gutter="20">
          <el-col :span="8"
            ><el-select
              v-model="form.tags"
              size="mini"
              placeholder="标签筛选"
              filterable
              multiple
              collapse-tags
              @change="getList"
            >
              <el-option
                v-for="item in options.label"
                :key="item.id"
                :label="item.tag"
                :value="item.id"
              >
              </el-option> </el-select
          ></el-col>
          <el-col :span="8"
            ><el-select
              v-model="form.roles"
              size="mini"
              placeholder="所有角色"
              filterable
              multiple
              collapse-tags
              @change="getList"
            >
              <el-option label="创建人" value="1"> </el-option>
              <el-option label="负责人" value="2"> </el-option>
              <el-option label="参与人" value="3"> </el-option>
              <el-option label="审批人" value="4"> </el-option>
              <el-option label="抄送人" value="5"> </el-option> </el-select
          ></el-col>
          <el-col :span="8"
            ><el-select
              v-model="form.projects"
              size="mini"
              placeholder="项目筛选"
              filterable
              multiple
              collapse-tags
              @change="getList"
            >
              <el-option
                v-for="item in options.project"
                :key="item.id"
                :label="item.title"
                :value="item.id"
              >
              </el-option> </el-select
          ></el-col>
        </el-row>
      </div>
      <div class="schedule_right_header">
        <span class="choseDate">{{ formatDate() }}</span>
      </div>
      <div class="schedule_right_list">
        <div v-if="listRight.length">
          <div
            class="schedule_right_item"
            v-for="item in listRight"
            :key="item.id"
            @click="openTaskDrawer(item.type, item.id, false, item.taskType)"
          >
            <span class="collect"
              ><span>{{ item.taskType === "2" ? "日程" : "任务" }}</span></span
            >
            <div class="schedule_right_item_left">
              <div class="title_or_label">
                <div style="max-width:80%;padding-top:4px">{{ item.title
                }}</div>
                <span
                  v-for="val in item.tags"
                  :key="val.id"
                  :style="{ background: val.color }"
                  >{{ val.tag }}</span
                >
              </div>
              <div class="time_or_status">
                <i
                  class="el-icon-time"
                  style="color: #666; font-size: 15px; margin-right: 6px"
                ></i
                ><span>{{ `${item.startTime} - ${item.endTime}` }}</span>
                <span :style="{ background: getTimeStatus(item, true) }">{{
                  getTimeStatus(item)
                }}</span>
                <div>
                  <i
                    class="el-icon-edit"
                    style="margin-left: 8px; color: #409eff"
                    @click.stop="
                      handleTaskEdit(item.type, item.id, item.taskType)
                    "
                    v-if="
                      [item.createBy, item.headUserId].includes(
                        $store.state.user.loginInfo.userId
                      ) && item.status === '0'
                    "
                  ></i>
                  <i
                    class="el-icon-delete-solid"
                    style="margin-left: 8px; color: #f56c6c"
                    @click.stop="handleTaskDelete(item.id, item.taskType)"
                    v-if="
                      [item.createBy, item.headUserId].includes(
                        $store.state.user.loginInfo.userId
                      ) && item.status === '0'
                    "
                  ></i>
                </div>
              </div>
            </div>
            <div class="schedule_right_item_right">
              <img
                :src="item.headUserAvatar"
                alt=""
                v-if="item.headUserAvatar"
              />
              <span v-else>{{ item.headUserName[0] }}</span>
            </div>
          </div>
        </div>
        <el-empty description="暂无日程" v-else></el-empty>
      </div>
    </div>
    <taskModel
      ref="taskModel"
      v-if="visible"
      :visible="visible"
      :close="() => (visible = false)"
      :propsObj="taskObjProps"
    />
    <taskDrawer
      v-if="visibleDrawer"
      :visible="visibleDrawer"
      :close="taskDrawerClose"
      :propsObj="taskObjProps"
      :finishLoading="finishLoading"
      :handleFinishTask="handleFinishTask"
      :handleTaskEdit="openTaskDrawer"
    />
  </div>
</template>

<script >
import FullCalendar from "@fullcalendar/vue";
import dayGridPlugin from "@fullcalendar/daygrid";
import timeGridPlugin from "@fullcalendar/timegrid";
import interactionPlugin from "@fullcalendar/interaction";
import listPlugin from "@fullcalendar/list";
import taskModel from "@/views/taskMassage/components/task/components/taskModel.vue";
import taskDrawer from "@/views/taskMassage/components/task/components/taskDrawer.vue";
import moment from "moment";
import { uuid } from "vue-uuid";
import {
  getProject,
  getTagList,
  finishTask,
  getTaskDetail,
  auditCheck,
  deleteTask,
  scheduleList,
} from "@/api/task/task.js";
export default {
  components: { FullCalendar, taskModel, taskDrawer },
  data() {
    return {
      visible: false,
      visibleDrawer: false,
      taskObjProps: {},
      taskObjProps: {},
      finishLoading: false,
      chooseDate: undefined,
      eventList: [],
      loading: false,
      listRight: [],
      form: {},
      options: {
        label: [],
        project: [],
      },
      calendarOptions: {
        plugins: [dayGridPlugin, timeGridPlugin, interactionPlugin, listPlugin],
        initialView: "dayGridMonth",
        locale: "zh-cn",
        firstDay: 1,
        aspectRatio: 1,
        height: "auto",
        headerToolbar: {
          left: "showMessage today",
          center: "prev title next",
          right: "dayGridMonth,dayGridWeek",
        },
        buttonText: {
          today: "今天",
          month: "月",
          week: "周",
          prev: "<",
          next: ">",
        },
        customButtons: {
          showMessage: {
            text: "+ 添加日程",
            click: this.handleTask,
          },
        },
        dayMaxEvents: 3,
        // 事件数量超出时更多显示链接汉化
        moreLinkContent: "+ 更多",
        // eventSources
        events: this.handleLoadingEvents,
        selectable: true,
        select: this.scheduleClick,
        eventClick: this.eventClick,
        updateEvent: this.updateEvent,
        lazyFetching: false, //缓存取数据
      },
      eventCallback: undefined,
      startDate: undefined,
      endDate: undefined,
      isRender: true,
    };
  },
  methods: {
    async getList(id, isEdit) {
      this.loading = true;
      this.listRight = [];
      const params = {
        startDate: this.startDate,
        endDate: this.endDate,
      };
      if (this.form.roles.length) {
        params.roles = this.form.roles.toString();
      }
      if (this.form.projects.length) {
        params.projects = this.form.projects.toString();
      }
      if (this.form.tags.length) {
        params.tags = this.form.tags.toString();
      }
      const res = await scheduleList(params);
      const list = [];
      const listRight = [];
      const listReset = [];
      res.data.forEach((item) => {
        if (item.taskList.length) {
          item.taskList.forEach((val) => {
            if (
              moment(val.endTime).format("YYYY-MM-DD") ===
              this.chooseDate.format("YYYY-MM-DD")
            ) {
              listRight.push(val);
            }
            const value = {
              id: val.id,
              title: val.title,
              start: moment(val.endTime).format("YYYY-MM-DD"),
              end: moment(val.endTime).format("YYYY-MM-DD"),
            };
            if (val.status === "0") {
              if (moment(val.endTime).isAfter(moment())) {
                value.classNames = ["inProgress"];
              } else {
                value.classNames = ["beOverdue"];
              }
            } else {
              value.classNames = ["finish"];
            }
            list.push(value);
            if (val) {
              listReset.push(val);
            }
          });
        }
      });
      this.listRight = listRight;
      this.listReset = listReset;
      this.loading = false;
      await this.eventCallback(list);
      const fullCalendar = this.$refs.fullCalendar.calendar;
      // if (id) {
      //   list.forEach((item) => {
      //     if (item.id == id) {
      //       if (isEdit) {
      //         const event = fullCalendar.getEventById(isEdit);
      //         event.remove();
      //       }
      //       fullCalendar.addEvent(item);
      //     }
      //   });
      // }
      const eventlist = fullCalendar.getEvents();
      if (eventlist.length) {
        eventlist.forEach((item) => {
          item.remove();
        });
      }
      list.forEach((item) => {
        fullCalendar.addEvent(item);
      });
    },
    async handleLoadingEvents(fetchInfo, callback) {
      this.eventCallback = callback;
      this.startDate = moment(fetchInfo.start).format("YYYY-MM-DD");
      this.endDate = moment(fetchInfo.end).format("YYYY-MM-DD");
      await this.getList();
    },
    getTimeStatus(row, isColor) {
      if (row.status === "0") {
        if (moment(row.endTime).isAfter(moment())) {
          return isColor ? "#409eff" : "进行中";
        } else {
          return isColor ? "#f56c6c" : "已逾期";
        }
      } else {
        if (row.status === "40") {
          return isColor ? "#909399" : "已完成";
        } else if (row.status === "30") {
          return isColor ? "#f56c6c" : "审批不通过";
        } else {
          return isColor
            ? "#409eff"
            : {
                10: "完成待审批",
                20: "审批中",
              }[row.status];
        }
      }
    },
    formatDate() {
      const weekdays = [
        "星期日",
        "星期一",
        "星期二",
        "星期三",
        "星期四",
        "星期五",
        "星期六",
      ];
      return (
        moment(this.chooseDate).format("YYYY-MM-DD") +
        `  ${weekdays[moment(this.chooseDate).day()]}`
      );
    },
    handleTask() {
      this.taskObjProps = {
        type: "schedule",
        getList: this.getList,
      };
      this.visible = true;
    },
    scheduleClick(val) {
      this.chooseDate = moment(val.start);
      const listRight = [];
      this.listReset.forEach((item) => {
        if (
          moment(item.endTime).format("YYYY-MM-DD") ===
          moment(val.start).format("YYYY-MM-DD")
        ) {
          listRight.push(item);
        }
      });
      this.listRight = listRight;
    },
    eventClick(calEvent) {
      this.chooseDate = moment(calEvent.event.start);
      const listRight = [];
      this.listReset.forEach((item) => {
        if (
          moment(item.endTime).format("YYYY-MM-DD") ===
          moment(calEvent.event.start).format("YYYY-MM-DD")
        ) {
          listRight.push(item);
        }
      });
      this.listRight = listRight;
    },
    taskDrawerClose() {
      this.$confirm("确认关闭操作吗", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          this.visibleDrawer = false;
        })
        .catch(() => {});
    },
    taskDrawerClose() {
      this.$confirm("确认关闭操作吗", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          this.visibleDrawer = false;
        })
        .catch(() => {});
    },
    async handleFinishTask(id) {
      this.$prompt("确认完成该任务吗？", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "info",
        inputPlaceholder: "请输入备注",
        inputType: "textarea",
      })
        .then(async ({ value }) => {
          this.finishLoading = true;
          const res = await finishTask(id, { remark: value });
          this.finishLoading = false;
          if (res.code === 200) {
            this.$message.success("操作成功！");
            this.visibleDrawer = false;
            this.getList(id);
          }
        })
        .catch(() => {});
    },
    async openTaskDrawer(type, id, isAgain, schedule) {
      const res = await getTaskDetail(id);
      const checkRes = await auditCheck(id);
      this.taskObjProps = {
        type:
          schedule === "2" ? "schedule" : type === "1" ? "standard" : "flow",
        getList: this.getList,
        taskDetailData: res.data,
        checkData: checkRes.data,
      };
      if (isAgain) return;
      this.visibleDrawer = true;
    },
    async handleTaskEdit(type, id, schedule) {
      const res = await getTaskDetail(id);
      const detailData = {};
      detailData.title = res.data.title;
      detailData.id = res.data.id;
      detailData.taskHead = [
        {
          nickName: res.data.headUserName,
          userId: res.data.headUserId,
          avatar: res.data.headUserAvatar,
          dept: { deptName: res.data?.headUserDept },
        },
      ];
      detailData.time = [res.data.startTime, res.data.endTime];
      detailData.circulateType = res.data.loopType;
      detailData.taskDescribe = res.data.description;
      if (res.data.participateInUsers?.length) {
        res.data.participateInUsers.forEach((item) => {
          item.nickName = item.name;
          item.userId = item.id;
        });
      }
      detailData.participants = res.data.participateInUsers;
      detailData.reviewType = res.data.auditUserType;
      detailData.label = res.data.tags;
      detailData.priority = res.data.priority;
      detailData.planWorking = this.handleEndTimeChange(
        res.data.startTime,
        res.data.endTime
      );
      if (res.data.auditUsers?.length) {
        res.data.auditUsers.forEach((item) => {
          item.nickName = item.name;
          item.userId = item.id;
        });
      }
      detailData.finishReview = res.data.auditUsers;
      if (res.data.copyOfUsers?.length) {
        res.data.copyOfUsers.forEach((item) => {
          item.nickName = item.name;
          item.userId = item.id;
        });
      }
      detailData.ccTo = res.data.copyOfUsers;
      if (res.data.checkOptions) {
        let data = res.data.checkOptions.split(",");
        let resetData = [];
        data.forEach((item) => {
          resetData.push({ h5Uid: uuid.v1(), content: item });
        });
        detailData.checkList = resetData;
      } else {
        detailData.checkList = [];
      }
      if (res.data.childTasks?.length) {
        res.data.childTasks.forEach((item) => {
          item.h5Uid = uuid.v1();
          item.time = [res.data.startTime, item.endTime];
          item.userId = item.id;
          item.id = item.id;
          item.taskHead = [
            {
              nickName: item.headUserName,
              userId: item.headUserId,
              avatar: item.headUserAvatar,
              dept: { deptName: item.headUserDept },
            },
          ];
        });
      }
      detailData.children = res.data.childTasks;
      detailData.fileList = res.data.files;
      this.taskObjProps = {
        type:
          schedule === "2" ? "schedule" : type === "1" ? "standard" : "flow",
        getList: this.getList,
        taskDetailData: detailData,
      };
      this.visible = true;
    },
    handleEndTimeChange(start, end) {
      if (start && end) {
        let startTime = moment(start);
        let endTime = moment(end);
        let diff = endTime.diff(startTime, "milliseconds");
        let days = diff / (1000 * 60 * 60 * 24);
        return Math.round(days * 10) / 10;
      }
    },
    async handleTaskDelete(id, type) {
      this.$confirm(`确认删除该${type === "2" ? "日程" : "任务"}吗？`, "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(async () => {
          const res = await deleteTask(id);
          if (res.code === 200) {
            this.$message.success("删除成功");
            this.getList();
            // const event = this.$refs.fullCalendar.calendar.getEventById(id);
            // event.remove();
          }
        })
        .catch(() => {});
    },
  },
  async mounted() {
    this.chooseDate = moment();
    this.options.label = (await getTagList()).data;
    this.options.project = (await getProject()).rows;
  },
};
</script>

<style lang="scss" scoped>
.schedule {
  display: flex;
  min-height: 84vh;
  ::v-deep .fc-daygrid-day-frame {
    min-height: 120px;
  }
  .schedule_left {
    width: 60%;
  }
  .schedule_right {
    width: 40%;
    background: #f9f9f9;
    position: relative;
    .schedule_right_header {
      padding: 20px;
      .choseDate {
        font-size: 28px;
        color: #409eff;
      }
    }
    .schedule_right_list {
      height: 75vh;
      overflow-y: scroll;
      ::v-deep .el-card {
        border: none;
      }
      padding: 0 16px;
      .schedule_right_item:hover {
        transform: translateY(-5px);
      }
      .schedule_right_item {
        position: relative;
        .collect {
          justify-content: flex-end;
          width: 40px;
          height: 40px;
          border-radius: 8px;
          background: #e9e9e9;
          position: absolute;
          right: 0;
          top: 0;
          clip-path: polygon(0 0, 100% 0, 100% 100%);
          background: #409eff;
          text-align: center;
          span {
            font-size: 12px;
            color: #fff;
            margin-left: 8px;
          }
        }
        transition: 150ms ease all;
        box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.1);
        border-radius: 6px;
        cursor: pointer;
        background: #fff;
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 12px 20px;
        margin-bottom: 12px;
        .schedule_right_item_left {
          display: flex;
          flex-direction: column;
          justify-content: center;
          width: 100%;
          .title_or_label {
          width: 100%;
            color: #666;
            font-size: 13px;
            display: flex;
            align-items: flex-start;
            span {
              color: #fff;
              font-size: 12px;
              padding: 4px 8px;
              border-radius: 12px;
              margin-left: 6px;
            }
          }
          .time_or_status {
            display: flex;
            align-items: center;
            margin-top: 12px;
            span:nth-of-type(1) {
              font-size: 13px;
              color: #666;
              margin-right: 6px;
            }
            span:nth-of-type(2) {
              font-size: 12px;
              color: #fff;
              padding: 4px 8px;
              border-radius: 4px;
            }
          }
        }
        .schedule_right_item_right {
          img {
            width: 35px;
            height: 35px;
            border-radius: 50%;
          }
          span {
            display: inline-block;
            width: 35px;
            height: 35px;
            border-radius: 50%;
            background: #1890ff;
            color: #fff;
            line-height: 35px;
            text-align: center;
            font-size: 16px;
          }
        }
      }
    }
    .searchTitle {
      // position: fixed;
      // top: 98px;
      // z-index: 10;
      padding: 0 20px;
      width: 100%;
      height: 56px;
      background: #fff;
      display: flex;
      align-items: center;
      ::v-deep .el-row {
        width: 100%;
      }
    }
  }
  ::v-deep .fc-toolbar.fc-header-toolbar {
    margin-bottom: 12px;
    margin-top: 12px;
    padding: 0 12px;
  }
  ::v-deep .inProgress {
    background: #dfecfa;
    margin: 0 5px 5px 5px;
    padding-left: 4px;
    border: none;
    border-left: 2px solid #409eff;
    border-radius: 2px;
    .fc-event-title {
      color: #409eff;
    }
  }
  ::v-deep .beOverdue {
    background: #f8e0e0;
    margin: 0 5px 5px 5px;
    padding-left: 4px;
    border: none;
    border-left: 2px solid #f56c6c;
    border-radius: 2px;
    .fc-event-title {
      color: #f56c6c;
    }
  }
  ::v-deep .finish {
    background: #dededf;
    margin: 0 5px 5px 5px;
    padding-left: 4px;
    border: none;
    border-left: 2px solid #757577;
    border-radius: 2px;
    .fc-event-title {
      color: #757577;
    }
  }
  ::v-deep .fc-toolbar-chunk {
    display: flex;
    align-items: center;
    .fc-button {
      font-size: 14px;
    }
    .fc-button-primary {
      background: #409eff;
      border: none;
    }
    .fc-button-primary:focus {
      box-shadow: none;
    }
    .fc-button-group {
      .fc-button-primary:not(:disabled).fc-button-active {
        background: #409eff;
        border: none;
        color: #fff;
      }
      .fc-button-primary:not(:disabled).fc-button-active:focus {
        box-shadow: none;
      }
      .fc-button-primary {
        background: #ecf5ff;
        border: none;
        color: #666;
      }
    }
  }
}
</style>